package api;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import models.Content;
import models.Message;
import models.Notification;
import models.Photo;
import models.User;
import models.Message.SharedContent;
import org.junit.Test;
import com.google.appengine.api.datastore.Link;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;

import controllers.Data;

import play.Play;
import play.mvc.Http.Cookie;
import play.mvc.Http.Request;
import play.mvc.Http.Response;
import play.mvc.Http.StatusCode;
import play.vfs.VirtualFile;
import util.JsonParserHelper;

import base.BaseTest;

public class FamiliarSharesPhoto extends BaseTest {
	
	private String from = "juan.gomez";
	
	@Test
	public void crudTest() throws Exception {
		
		//Loggin en el sistema de Juan Gomez familiar de Eva perez
		Map<String, String> loginUserParams = new HashMap<String, String>();
		loginUserParams.put("username", from+"@B");
		loginUserParams.put("password", "secret2");
		// Login here so the following request will be authenticated:
		Response response = POST("/login", loginUserParams);
		assertStatus(StatusCode.FOUND, response);
		cookies.putAll(response.cookies);
		
		//Comprobacion de que juan gomez todavía no ha subida ninguna imagen a batzen.
		Request request = newRequest();
        request.cookies.putAll(cookies);
		response = GET(request, "/api/me/photos");
		assertStatus(StatusCode.OK, response);
		Data<Photo> photos = JsonParserHelper.toPhotoCollection(response.out.toByteArray());
		assertTrue("La usuario juan gomez no tiene ninguna foto", photos.data.size()==0);
		
		//Juan Gomez sube una imagen a batzen.
		Map<String, String> parameters = new HashMap<String, String>();
		Map<java.lang.String, java.io.File> files = new HashMap<java.lang.String, java.io.File>();
		File image = locateFile("atom-1.jpeg");
		assertNotNull("El fichero atom-1.jpeg especificado no existe", image);
		files.put("data", image);
		request = newRequest();
        request.cookies.putAll(cookies);
		response =  POST(request, "/api/me/photos", parameters, files);
		String location = response.getHeader("location");
		assertNotNull(location);
		Photo photo = JsonParserHelper.toPhoto(response.out.toByteArray());
		assertTrue("El propietario de la foto tiene que ser Juan Gomez.", photo.owner.username.equals(from));
		
		//Se verifica que Juan Gomez a subida una imagen a batzen
		request = newRequest();
        request.cookies.putAll(cookies);
		response = GET(request, "/api/me/photos");
		assertStatus(StatusCode.OK, response);
		photos = JsonParserHelper.toPhotoCollection(response.out.toByteArray());
		assertTrue("Juan Gomez tiene una imagen subida.", photos.data.size()==1);
		
		//Recupero la lista de internos de un familiar
		request = newRequest();
        request.cookies.putAll(cookies);
		response = GET(request, "/api/me/internals");
		assertStatus(StatusCode.OK, response);
		
		JsonObject users = JsonParserHelper.toJsonObject(response.out.toByteArray());
		assertTrue(from + " tiene un interno", users.get("total").getAsInt()==1);
		JsonObject internal = users.get("data").getAsJsonArray().get(0).getAsJsonObject();
		assertTrue("El familiar interna se llama eva perez.", internal.get("username").getAsString().equals("eva.perez"));
		
		//Comprobacion: Juan Gomez comparte una foto con Eva perez
		JsonObject message = new JsonObject();
		message.addProperty("body", "Cuerpo del mensaje");
		JsonArray tos = new JsonArray();
		JsonObject to = new JsonObject();
		to.addProperty("id", internal.get("id").getAsNumber());
		to.addProperty("firstName", internal.get("firstName").getAsString());
		tos.add(to);
		message.add("receivers", tos);
		JsonArray contents = new JsonArray();
		JsonObject content = new JsonObject();
		content.addProperty("type", Content.ContentType.PHOTO.getName());
		content.addProperty("id", photo.id);
		content.addProperty("source", location);
		contents.add(content);
		message.add("contents", contents);
		request = newRequest();
        request.cookies.putAll(cookies);
		response = POST(request,"/api/me/outbox", "application/json", message.toString());
		assertStatus(StatusCode.OK,response);
		
		// Comprobacion: Juan Gomez debe tener un mensaje en su bandeja de salida
	
		/*
		//Comprobacion: Juan Gomez debe tener un mensaje en su bandeja de salida
		response =  GET("/api/me/outbox");
		assertStatus(StatusCode.OK, response);
		Data<Message> messages = JsonParserHelper.toMessageCollection(response.out.toByteArray());
		assertTrue("Juan gomez ha enviado un mensaje", messages.data.size()==1);
		Message inMessage = messages.data.get(0);
		response =  GET("/api/me/outbox/" + inMessage.id);
		assertStatus(StatusCode.OK, response);
		inMessage = JsonParserHelper.toMessage(response.out.toByteArray());
		//System.out.println("From: " + inMessage.from.id + " To:" + inMessage.to.id + "Internal:" + internal.get("id").getAsNumber() + ".");
		//assertTrue("El mensaje ha sido enviado a Eva Perez",inMessage.to.id.longValue()==internal.get("id").getAsNumber().longValue());
		response =  GET("/api/me/outbox/" + inMessage.id);
		assertStatus(StatusCode.OK, response);
		
		//Mandamos el mismo mensaje de nuevo al mismo destinatario
		request = newRequest();
        request.cookies.putAll(cookies);
		response = POST(request,"/api/me/outbox", "application/json", message.toString());
		assertStatus(StatusCode.OK,response);
		
		//Comprobacion: Juan Gomez debe tener un mensaje en su bandeja de salida
		response =  GET("/api/me/outbox");
		assertStatus(StatusCode.OK, response);
		messages = JsonParserHelper.toMessageCollection(response.out.toByteArray());
		assertTrue("Juan gomez ha enviado un mensaje", messages.data.size()==2);
		
		//Juan Gomez se deslogea del sistema
		response =  GET("/logout");
		clearCookies();
		cookies.clear();
		assertStatus(StatusCode.FOUND, response);
		
		
		//Login de eva perez
		loginUserParams = new HashMap<String, String>();
		loginUserParams.put("username", "eva.perez@B");
		loginUserParams.put("password", "secret1");
		// Login here so the following request will be authenticated:
		response = POST("/login", loginUserParams);
		assertStatus(StatusCode.FOUND, response);
		cookies.putAll(response.cookies);
		
		//Comprobacion: el buzon de salida de eva perez no debe tener ningún mensaje.
		request = newRequest();
        request.cookies.putAll(cookies);
        response =  GET(request, "/api/me/outbox");
        assertStatus(StatusCode.OK, response);
		messages = JsonParserHelper.toMessageCollection(response.out.toByteArray());
		assertTrue("Eva perez no ha enviado mensaje alguno", messages.data.size()==0);
		
		//Comprobacion: la usuario eva perez debe tener una notificacion del tipo inbox.
		request = newRequest();
        request.cookies.putAll(cookies);
        response =  GET(request, "/api/me/notifications");
        assertStatus(StatusCode.OK, response);
        Data<Notification> notifications = JsonParserHelper.toNotificationCollection(response.out.toByteArray());
        assertTrue("Control paginación-notificaciones", notifications.total >= notifications.data.size());
        assertTrue("Eva perez debe tener dos notificaciones",  notifications.data.size()==2);
        Notification notification = notifications.data.get(0);
        assertTrue("La notificacion de eva perez ha de ser de tipo INBOX", notification.type.compareTo(Notification.NotificationType.INBOX)==0);
        
        request = newRequest();
        request.cookies.putAll(cookies);
        response =  GET(request, "/api/" + notification.owner.id + "/profile");
        JsonObject user = JsonParserHelper.toJsonObject(response.out.toByteArray());
        assertTrue("El propietario de la notificación es eva perez.",user.get("username").getAsString().equals("eva.perez"));
		
        //Comprobacion: el buzon de entrada eva debe tener un mensaje.
		request = newRequest();
        request.cookies.putAll(cookies);
        response =  GET(request, "/api/me/inbox");
		assertStatus(StatusCode.OK, response);
		messages = JsonParserHelper.toMessageCollection(response.out.toByteArray());
		assertTrue("Eva perez ha recibido dos mensajes", messages.data.size()==2);
		inMessage = messages.data.get(0);
		
		//Recuperamos el detalle del mensaje
		request = newRequest();
        request.cookies.putAll(cookies);
		response = GET(request, "/api/me/inbox/" + inMessage.id);
		
		Message detailedMessage = JsonParserHelper.toMessage(response.out.toByteArray());
		//assertTrue("El mensaje no esta leido", detailedMessage.readed);
		
		//Comprobacion: el emisor del mensaje es juan gomez.
		response = GET("/api/" + detailedMessage.from.id + "/profile");
		assertStatus(StatusCode.OK, response);
		JsonObject profile = JsonParserHelper.toJsonObject(response.out.toByteArray());
		assertTrue("El mensaje ha sido enviado por " + from, from.equals(profile.get("username").getAsString()));
		assertTrue("Sólo se ha compartido un contenido", inMessage.contents.size()==1);
		SharedContent shared = inMessage.contents.get(0);
		if(shared.type.equals(Content.ContentType.PHOTO)) {
			request = newRequest();
	        request.cookies.putAll(cookies);
	        response =  GET(request, "/api/me/photos/" + shared.id);
		}
		
		request = newRequest();
        request.cookies.putAll(cookies);
        response =  GET(request, "/api/me/photos?owned=false");
        photos = JsonParserHelper.toPhotoCollection(response.out.toByteArray());
        assertTrue("Sólo tiene una imagen compartida con el", photos.data.size()==1);
        assertTrue("Debe ser la misma imagen.", photos.data.get(0).id.longValue() == shared.id.longValue());*/
	}
	
}